package com.freewater.helloworld.application;

import com.freewater.helloworld.entity.Book;
import com.freewater.helloworld.entity.Book_;
import com.freewater.helloworld.entity.Person;
import com.freewater.helloworld.entity.User;
import com.freewater.helloworld.query.Queries_;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.criteria.CriteriaBuilder;
import org.hibernate.query.Page;

import java.util.List;
import java.util.Map;

import static com.freewater.helloworld.utils.JpaUtils.inSession;
import static jakarta.persistence.Persistence.createEntityManagerFactory;
import static java.lang.System.out;
import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION;
import static org.hibernate.tool.schema.Action.CREATE;

public class HelloJpa {
    public static void main(String[] args) {
        var factory = createEntityManagerFactory("jap-demo",
                // export the inferred database schema
                Map.of(JAKARTA_HBM2DDL_DATABASE_ACTION, CREATE));

        // persist an entity
        inSession(factory, entityManager -> {
            entityManager.persist(new Book("9781932394153", "Hibernate in Action"));
            entityManager.persist(new Person(1, "freewater", 21, "chengdu handsome boy"));
            entityManager.persist(new User(1, "yujishui", "123456"));
        });

        // query data using HQL
        inSession(factory, entityManager -> {
            var query1 = entityManager.createQuery("from Book ", Book.class);
            out.println(query1.getSingleResult());
            var query2 = entityManager.createQuery("from Person", Person.class);
            out.println(query2.getSingleResult());
            var query3 = entityManager.createQuery("from User", User.class);
            out.println(query3.getSingleResult());
        });

        // query data using criteria API
        inSession(factory, entityManager -> {
            var result = queryByCriteria(entityManager, factory);
            out.println(result);
        });

        // query data using hql
        inSession(factory, entityManager -> {
            Book book = queryByHql(entityManager);
            out.println(book);
        });
    }

    private static String queryByCriteria(EntityManager entityManager,
                                          EntityManagerFactory factory) {
        CriteriaBuilder builder = factory.getCriteriaBuilder();
        var query = builder.createQuery(String.class);
        var book = query.from(Book.class);
        query.select(builder.concat(builder.concat(book.get(Book_.isbn),
                        builder.literal(": ")),
                book.get(Book_.title)));
        var selectQuery = entityManager.createQuery(query);
        return selectQuery.getSingleResult();
    }

    private static Book queryByHql(EntityManager entityManager) {
        List<Book> books = Queries_.findBooksByTitleWithPagination(entityManager, "Hibernate%", Page.first(20));
        assert books.size() == 1;
        return books.getFirst();
    }
}
